// Package api 的号码包模块：提供创建、列表、CSV 明细上传、明细查询与删除接口。
package api

import (
	"encoding/csv"
	"encoding/json"
	"io"
	"net/http"
	"strconv"
	"time"

	"github.com/we-pay-kit/we-pay-kit/internal/db"
	"github.com/we-pay-kit/we-pay-kit/internal/repository"
)

type NumberPackageHandler struct {
	repo  *repository.NumberPackageRepository
	dRepo *repository.NumberPackageDetailRepository
}

func NewNumberPackageHandler() *NumberPackageHandler {
	database := db.GetDB()
	return &NumberPackageHandler{repo: repository.NewNumberPackageRepository(database), dRepo: repository.NewNumberPackageDetailRepository(database)}
}

// POST /api/v1/number-packages  (JSON创建基本信息)
func (h *NumberPackageHandler) CreatePackage(w http.ResponseWriter, r *http.Request) {
	var in struct {
		PackageName string `json:"package_name"`
		TotalCount  int    `json:"total_count"`
		CreatedBy   string `json:"created_by"`
	}
	if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	np := &repository.NumberPackage{PackageName: in.PackageName, TotalCount: in.TotalCount, Status: "UPLOADING", CreatedBy: in.CreatedBy}
	id, err := h.repo.Create(r.Context(), np)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(map[string]any{"id": id})
}

// POST /api/v1/number-packages/upload?id=1 (CSV 上传明细，每行: phone_number[,user_id])
func (h *NumberPackageHandler) UploadDetailsCSV(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.ParseInt(r.URL.Query().Get("id"), 10, 64)
	if id == 0 {
		http.Error(w, "missing id", http.StatusBadRequest)
		return
	}
	reader := csv.NewReader(r.Body)
	count := 0
	for {
		rec, err := reader.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		if len(rec) == 0 {
			continue
		}
		phone := rec[0]
		var uid *string
		if len(rec) > 1 && rec[1] != "" {
			v := rec[1]
			uid = &v
		}
		_, err = h.dRepo.Add(r.Context(), &repository.NumberPackageDetail{PackageID: id, PhoneNumber: phone, UserID: uid, Status: "UNUSED"})
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		count++
	}
	now := time.Now()
	_ = h.repo.UpdateStatus(r.Context(), id, "COMPLETED")
	// Update uploaded_count
	// For simplicity, not implemented: aggregate count in DB; rely on TotalCount provided.
	_ = json.NewEncoder(w).Encode(map[string]any{"uploaded": count, "upload_time": now.Format(time.RFC3339)})
}

// GET /api/v1/number-packages
func (h *NumberPackageHandler) ListPackages(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	limit, _ := strconv.Atoi(q.Get("limit"))
	offset, _ := strconv.Atoi(q.Get("offset"))
	list, err := h.repo.List(r.Context(), limit, offset)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(list)
}

// GET /api/v1/number-packages/details?package_id=1
func (h *NumberPackageHandler) ListDetails(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	pid, _ := strconv.ParseInt(q.Get("package_id"), 10, 64)
	if pid == 0 {
		http.Error(w, "missing package_id", http.StatusBadRequest)
		return
	}
	limit, _ := strconv.Atoi(q.Get("limit"))
	offset, _ := strconv.Atoi(q.Get("offset"))
	list, err := h.dRepo.ListByPackage(r.Context(), pid, limit, offset)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(list)
}

// DELETE /api/v1/number-packages?id=1
func (h *NumberPackageHandler) DeletePackage(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	id, _ := strconv.ParseInt(q.Get("id"), 10, 64)
	if id == 0 {
		http.Error(w, "missing id", http.StatusBadRequest)
		return
	}
	if err := h.repo.Delete(r.Context(), id); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
